package com.gticket.customerbackend.handler;

import com.gticket.customerbackend.dlx.DlxSender;
import com.gticket.customerbackend.pojo.CinemaActualSeats;
import com.gticket.customerbackend.pojo.CinemaCode;
import com.gticket.customerbackend.pojo.Movie;
import com.gticket.customerbackend.service.MovieScheduleService;
import com.rabbitmq.client.Channel;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeoutException;

/**
 * @author 李浩楠
 * @date 2019/11/23 下午2:17
 */

@RestController
@Data
@Slf4j
@Api(value = "后段排片Controller" , tags = "排片模块handler")
public class MovieScheduleHandler {

    @Autowired
    private MovieScheduleService movieScheduleService;
    // 电影单
    private List<Movie> movies;

    // 返回所有的分院信息从ConsoleHandler里面拿


    // 返回所有的电影(以后改成可用的)
    @GetMapping("/getAllMovie")
    @ResponseBody
    @ApiOperation(value = "返回所有的电影",notes = "必传参数: 无")
    public List<Movie> getAllMovie(String db) {
        //封装对象
        CinemaCode cinemaCode = new CinemaCode();
        cinemaCode.setDb(db);
        movies = movieScheduleService.getAllMovies(cinemaCode);
        return movies;
    }

    // 插入片的信息以及排片信息
    @PostMapping("/schedulingMovie")
    @ResponseBody
    public String schedulingMovie(String db, String movie_name, String movie_englishname,
                                  String movie_act, String movie_descr, String movie_detail,
                                  String movie_type, String movie_country, Integer movie_time,
                                  String movie_date, BigDecimal movie_price,
                                  int cinema_id, int ch_id, String start_time, String end_time, String fs_date,
                                  MultipartFile picture, HttpServletRequest request) {
        //封装对象
        CinemaCode cinemaCode = new CinemaCode();
        cinemaCode.setDb(db);

        // 对上传的图片在工程目录下进行保存
        String path = request.getServletContext().getRealPath("/");
        File imageFile = new File(path  + "G-Ticket/customerbackend/src/main/resources/static/img");

        String picture_name = picture.getOriginalFilename();

        // 不存在则创建文件夹
        if(!imageFile.exists()) {
            imageFile.mkdirs();
        }
        System.out.println("imageFile" + imageFile);

        // 如果没有影片图片那就是默认的，在此处设置为默认
        if(movie_detail == null) {
            movie_detail = "/img/default.png";
        }

        // 随机生成文件名
        String fileName = UUID.randomUUID().toString();
        fileName += picture_name.substring(picture_name.indexOf("."));

        //确定该文件的路径
        File upFile = new File(imageFile,fileName );
        // 存放图片
        try{
            picture.transferTo(upFile);
            //log.info("存储图片");
        } catch (IOException e) {
            e.printStackTrace();
        }

        //把图片的地址赋给movie_detail
        movie_detail = upFile.toString();

        if(movieScheduleService.insertNewMovie(cinemaCode,movie_name,movie_englishname,
                movie_act,movie_descr,movie_detail,movie_type,movie_country,movie_time
                  ,movie_date,movie_price)) {
            // 取出刚刚上传好的id, 把影片名字设为唯一键目的是为了方便取值。
            int movie_id = movieScheduleService.getMovieIdByName(cinemaCode,movie_name);
            //复制actual seat信息,第一首先从original表中拿取数据,用actual seat的pojo来装
            CinemaActualSeats cinemaActualSeats = movieScheduleService.getTempSeats(cinemaCode,cinema_id,ch_id);
            // 首先新建as表，直接插入需要的数据
            if(movieScheduleService.createActualSeats(cinemaCode,cinema_id,ch_id,cinemaActualSeats.getRow_1(),
                    cinemaActualSeats.getRow_2(),cinemaActualSeats.getRow_3(),cinemaActualSeats.getRow_4(),
                    cinemaActualSeats.getRow_5(),cinemaActualSeats.getRow_6(),cinemaActualSeats.getRow_7(),
                    cinemaActualSeats.getRow_8(),cinemaActualSeats.getRow_9(),cinemaActualSeats.getRow_10(),
                    cinemaActualSeats.getRow_11(),cinemaActualSeats.getRow_12(),cinemaActualSeats.getRow_13(),
                    cinemaActualSeats.getRow_14(),cinemaActualSeats.getRow_15(),cinemaActualSeats.getCh_capacity())){
                // 拿取刚刚插入as_id
                int as_id = movieScheduleService.last_id();
                // 到这里正式插入排片表
                String movie_version = "国语3d";
                BigDecimal movie_realprice = movie_price;
                if(movieScheduleService.createNewMovieSchedule(cinemaCode,cinema_id,ch_id,movie_id,as_id,start_time,end_time,fs_date,movie_version,movie_realprice)){
                    // 拿取刚刚插入的fs_id
                    int fs_id = movieScheduleService.last_id();
                    // 把消息放入队列，等过期进入死信队列更改flag值
                    try {
                        //创建SimpleDateFormat对象实例并定义好转换格式
                        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
                        Date date = null;
                        date = sdf.parse(fs_date+" "+start_time);
                        // 获取现在的时间
                        Date now = sdf.parse(sdf.format(new Date()));
                        Date end_date = sdf.parse(fs_date+" "+end_time);
                        // 获取两个相差时间的毫秒数，因为是电影开始后30分钟才改变所以加上30分钟的毫秒数
                        long diff = date.getTime() - now.getTime() + 1800000;
                        // 获取电影结束时间，东哥那边要
                        long diff2 = end_date.getTime() - now.getTime();
                        // 往死信队列中发信息，等待过期(暂时为60s秒，以后改成diff)
                        DlxSender.sendMessage(db+","+fs_id,diff);
                        DlxSender.sendMessage2(db+","+fs_id,diff2);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    // 记得写消费者方法

                    // 至此排片成功
                    return "排片成功";
                }
            }
        }
        return "排片失败";
    }

    @GetMapping("/getScheduledMovieByDate")
    @ResponseBody
    public List<Movie> getScheduledMovieByDate(String db,Integer cinema_id,Integer ch_id,String date) {
        //封装对象
        CinemaCode cinemaCode = new CinemaCode();
        cinemaCode.setDb(db);
        System.out.println("============");
        System.out.println(date);
        System.out.println("============");
        // 这里先假设传进来的日期是YYYY-MM-DD格式
        movies = movieScheduleService.getScheduledMovieByDate(cinemaCode,cinema_id,ch_id,date);
        for(int i = 0; i < movies.size(); i++) {
            movies.get(i).setMovie_name(
                    movieScheduleService.
                            getMovieByMovieId(cinemaCode,movies.get(i).getMovie_id())
                            .getMovie_name()
            );
        }
        return movies;
    }

    @PostMapping("/schedulingMovieByExists")
    @ResponseBody
    public String schedulingMovieByExists(String db,int movie_id,Integer cinema_id,Integer ch_id,String start_time, String end_time,String fs_date) {
        //封装对象
        CinemaCode cinemaCode = new CinemaCode();
        cinemaCode.setDb(db);
            //复制actual seat信息,第一首先从original表中拿取数据,用actual seat的pojo来装
            CinemaActualSeats cinemaActualSeats = movieScheduleService.getTempSeats(cinemaCode,cinema_id,ch_id);
            // 首先新建as表，直接插入需要的数据
            if(movieScheduleService.createActualSeats(cinemaCode,cinema_id,ch_id,cinemaActualSeats.getRow_1(),
                    cinemaActualSeats.getRow_2(),cinemaActualSeats.getRow_3(),cinemaActualSeats.getRow_4(),
                    cinemaActualSeats.getRow_5(),cinemaActualSeats.getRow_6(),cinemaActualSeats.getRow_7(),
                    cinemaActualSeats.getRow_8(),cinemaActualSeats.getRow_9(),cinemaActualSeats.getRow_10(),
                    cinemaActualSeats.getRow_11(),cinemaActualSeats.getRow_12(),cinemaActualSeats.getRow_13(),
                    cinemaActualSeats.getRow_14(),cinemaActualSeats.getRow_15(),cinemaActualSeats.getCh_capacity())){
                // 拿取刚刚插入as_id
                int as_id = movieScheduleService.last_id();
                // 到这里正式插入排片表
                String movie_version = "国语3d";
                BigDecimal movie_realprice = movieScheduleService.getMovieByMovieId(cinemaCode, movie_id).getMovie_price();
                if(movieScheduleService.createNewMovieSchedule(cinemaCode,cinema_id,ch_id,movie_id,as_id,start_time,end_time,fs_date,movie_version,movie_realprice)){
                    // 拿取刚刚插入的fs_id
                    int fs_id = movieScheduleService.last_id();
                    // 把消息放入队列，等过期进入死信队列更改flag值
                    try {
                        //创建SimpleDateFormat对象实例并定义好转换格式
                        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
                        Date date = null;
                        Date end_date = null;
                        date = sdf.parse(fs_date+" "+start_time);
                        end_date = sdf.parse(fs_date+" "+end_time);
                        // 获取现在的时间
                        Date now = sdf.parse(sdf.format(new Date()));
                        // 获取两个相差时间的毫秒数，因为是电影开始后30分钟才改变所以加上30分钟的毫秒数
                        long diff = date.getTime() - now.getTime() + 1800000;
                        long diff2 = end_date.getTime() - now.getTime();
                        // 往死信队列中发信息，等待过期（60秒只是为了演示用，记得以后改成diff）
                        DlxSender.sendMessage(db+","+fs_id,diff);
                        DlxSender.sendMessage2(db+","+fs_id,diff2);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    // 记得写消费者方法

                    // 至此排片成功
                    return "排片成功";
            }
        }
        return "排片失败";
    }

    //死信监听
    @RabbitListener(queues = "dlx_queue1_schedule")
    public void process1(Message message, Channel channel,byte[] msg) {
        System.out.println("消费者process2开始消费");
        String[] temp = new String(msg).split(",");
        String db = temp[0];
        int fs_id = Integer.valueOf(temp[1]);
        //封装对象
        CinemaCode cinemaCode = new CinemaCode();
        cinemaCode.setDb(db);
        long deliveryTag = message.getMessageProperties().getDeliveryTag();
        try {
                log.info("死信处理: fs_id => " + fs_id);
                System.out.println("死信处理: fs_id => " + fs_id);
                //如果状态未被修改  则修改状态位已失效
                log.info("排片表： id =>" + fs_id + "已失效");
                System.out.println("排片表： id =>" + fs_id + "已失效");
                movieScheduleService.updateMovieScheduleFlag(cinemaCode,fs_id);
                channel.basicAck(deliveryTag, false);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                channel.close();
            } catch (IOException e) {

            } catch (TimeoutException e) {
                e.printStackTrace();
            }
        }

    }

}
